package com.medvalley.tcm.service.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.medvalley.tcm.base.BusinessException;
import com.medvalley.tcm.base.Constants;
import com.medvalley.tcm.base.EmptyException;
import com.medvalley.tcm.cache.RedisCache;
import com.medvalley.tcm.dao.*;
import com.medvalley.tcm.domain.*;
import com.medvalley.tcm.pojo.SickInfoBrief;
import com.medvalley.tcm.service.ReportService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class ReportServiceImpl implements ReportService {

    @Autowired
    private SickUserDao sickUserDao;

    @Autowired
    private UserInfoDao userInfoDao;

    @Autowired
    private SickInfoDao sickInfoDao;

    @Autowired
    private SickYangShengDao sickYangShengDao;

    @Autowired
    private YangShengConfigDao yangShengConfigDao;

    @Autowired
    private YangShengXieZiDao yangShengXieZiDao;

    @Autowired
    private YangShengSportDao yangShengSportDao;

    @Autowired
    private YangShengSeaonDao yangShengSeaonDao;

    @Autowired
    private YangShengEatDao yangShengEatDao;

    @Autowired
    private YangShengTeaDao yangShengTeaDao;

    @Autowired
    private YangShengMethodDao yangShengMethodDao;

    @Autowired
    private YangShengAcupunctureDao yangShengAcupunctureDao;

    @Autowired
    private RedisCache redisCache;

    @Override
    public List<SickInfoBrief> findReportList(String phone) {
        UserInfo userInfo = userInfoDao.findOneByPhone(phone);
        long userId = userInfo.getId();
        List<SickAndUser> sickAndUsers = sickUserDao.findAllByUserId(userId);
        if (sickAndUsers == null || sickAndUsers.size() == 0) {
            return null;
        }
        List<Long> ids = Lists.newArrayList();
        sickAndUsers.forEach(temp -> {
            ids.add(temp.getSickId());
        });
        List<SickInfo> sickInfos = sickInfoDao.findAllByIdIn(ids);
        List<SickInfoBrief> returnList = Lists.newArrayList();
        for (SickInfo s : sickInfos) {
            SickInfoBrief sickInfoBrief = new SickInfoBrief();
            BeanUtils.copyProperties(s, sickInfoBrief);
            returnList.add(sickInfoBrief);
        }
        return returnList;
    }

    @Override
    public List<SickInfoBrief> findReportListByDate(Date begin, Date end, String orgName) {
        List<SickInfo> sickInfos = Lists.newArrayList();
        if (StringUtils.isEmpty(orgName)) {
            sickInfos = sickInfoDao.findAllByCreateTimeBetween(begin, end);
        } else {
            sickInfos = sickInfoDao.findAllByCreateTimeBetweenAndDiagnosticMechanismName(begin, end, orgName);
        }
        List<SickInfoBrief> returnList = Lists.newArrayList();
        for (SickInfo s : sickInfos) {
            SickInfoBrief sickInfoBrief = new SickInfoBrief();
            BeanUtils.copyProperties(s, sickInfoBrief);
            returnList.add(sickInfoBrief);
        }
        return returnList;
    }


    @Override
    public SickInfoBrief findReportBrief(String phone, long reportId) {
        SickAndUser sickAndUser = sickUserDao.findOneBySickIdAndPhone(reportId, phone);
        if (sickAndUser == null) {
            throw new BusinessException("查无此报告");
        }
        SickInfo sickInfo = sickInfoDao.findById(reportId).get();
        SickInfoBrief sickInfoBrief = new SickInfoBrief();
        BeanUtils.copyProperties(sickInfo, sickInfoBrief);
        return sickInfoBrief;
    }

    @Override
    public List<SickAndUser> relateReportByPhone(String userPhone, String inputPhone) {
        List<SickAndUser> sickAndUsers = new ArrayList<>();
        UserInfo userInfo = userInfoDao.findOneByPhone(userPhone);
        long userId = userInfo.getId();
        List<SickInfo> sickInfos = sickInfoDao.findAllByPatientPhone(inputPhone);
        if (sickInfos != null && sickInfos.size() > 0) {
            for (SickInfo s : sickInfos) {
                long sickId = s.getId();
                int isPrint = s.getIsPrint();
                if (isPrint == 0) {
                    // 必须是完成的状态才可以关联
                    continue;
                }
                SickAndUser sickAndUser = sickUserDao.findOneBySickIdAndUserId(sickId, userId);
                if (sickAndUser == null) {
                    SickAndUser tempSickAndUser = new SickAndUser();
                    tempSickAndUser.setSickId(sickId);
                    tempSickAndUser.setUserId(userId);
                    tempSickAndUser.setPhone(userPhone);
                    tempSickAndUser.setSickCreateTime(s.getCreateTime());
                    sickUserDao.save(tempSickAndUser);
                    sickAndUsers.add(tempSickAndUser);
                }
            }
        } else {
            throw new BusinessException("没有找到相关报告");
        }
        return sickAndUsers;
    }

    @Override
    public Map<String, Object> webGetReportId(String phone, String barCode) {
        SickInfo report = sickInfoDao.findOneByBarCode(barCode);
        if (report == null) {
            throw new BusinessException("提取码有误，未找到报告");
        }
        String patientPhone = report.getPatientPhone();
        if (!phone.equals(patientPhone)) {
            throw new BusinessException("手机号和提取码不匹配");
        }
        if (report.getIsPrint() == 0) {
            throw new BusinessException("医生诊断中");
        }
        long reportId = report.getId();
        SickAndUser su = sickUserDao.findOneBySickIdAndPhone(reportId, phone);
        if (su == null) {
            // 创建临时绑定关系
            SickAndUser newSickUser = new SickAndUser();
            newSickUser.setUserId(-1);
            newSickUser.setSickId(report.getId());
            newSickUser.setPhone(phone);
            newSickUser.setSickCreateTime(report.getCreateTime());
            sickUserDao.save(newSickUser);
        }
        Map<String, Object> returnMap = Maps.newHashMap();
        returnMap.put("reportId", report.getId());
        String token = this.generateToken(patientPhone);
        returnMap.put("token", token);
        return returnMap;
    }

    @Override
    public SickAndUser relateReportByBarCode(String phone, String sickPwd, String barCode) {
        UserInfo userInfo = userInfoDao.findOneByPhone(phone);
        long userId = userInfo.getId();
        SickInfo sickInfo = sickInfoDao.findOneByBarCode(barCode);
        if (sickInfo == null) {
            throw new EmptyException("没有查到报告");
        }
        String extractCode = sickInfo.getExtractCode();
        if (!sickPwd.equals(extractCode)) {
            throw new BusinessException("提取密码错误");
        }
        int isPrint = sickInfo.getIsPrint();
        if (isPrint == 0) {
            throw new BusinessException("医生诊断中");
        }
        long sickId = sickInfo.getId();
        SickAndUser sickAndUser = sickUserDao.findOneBySickIdAndUserId(sickId, userId);
        if (sickAndUser != null) {
            throw new BusinessException("已经绑定过");
        }
        SickAndUser newSickUser = new SickAndUser();
        newSickUser.setUserId(userId);
        newSickUser.setSickId(sickId);
        newSickUser.setPhone(phone);
        newSickUser.setSickCreateTime(sickInfo.getCreateTime());
        sickUserDao.save(newSickUser);
        return newSickUser;
    }

    @Override
    public boolean checkUser2Sick(String phone, long reportId) {
        SickAndUser sickAndUser = sickUserDao.findOneBySickIdAndPhone(reportId, phone);
        if (sickAndUser == null) {
            return false;
        }
        // 绑定养生建议
        addYangShengAdvice(reportId);
        return true;
    }

    @Override
    public List<YangShengXieZi> findXieZiBySickId(long sickId) {
        SickYangSheng sickYangSheng = this.getSickYangShengBySickId(sickId);
        String xieZiIds = sickYangSheng.getXieZiId();
        List<Long> ids = this.getIds(xieZiIds);
        List<YangShengXieZi> results = yangShengXieZiDao.findAllByIdIn(ids);
        return results;
    }

    @Override
    public List<YangShengXieZi> findXieZiRandom(int num) {
        List<YangShengXieZi> xieZis = yangShengXieZiDao.findAllByRand(num);
        return xieZis;
    }

    @Override
    public List<YangShengSports> findSportBySickId(long sickId) {
        SickYangSheng sickYangSheng = this.getSickYangShengBySickId(sickId);
        String sportIds = sickYangSheng.getSportId();
        List<Long> ids = this.getIds(sportIds);
        List<YangShengSports> results = yangShengSportDao.findAllByIdIn(ids);
        return results;
    }

    @Override
    public List<YangShengSports> findSportRandom(int num) {
        return null;
    }

    @Override
    public List<YangShengSeaon> findSeaonBySickId(long sickId) {

        SickYangSheng sickYangSheng = this.getSickYangShengBySickId(sickId);
        String seasonIds = sickYangSheng.getSeasonId();
        List<Long> ids = this.getIds(seasonIds);
        List<YangShengSeaon> results = yangShengSeaonDao.findAllByIdIn(ids);
        return results;
    }

    @Override
    public List<YangShengSeaon> findSeasonRandom(int num) {
        int tag = this.getSeasonTag();
        List<YangShengSeaon> seasons = yangShengSeaonDao.findAllByRand(tag, num);
        return seasons;
    }

    @Override
    public List<YangShengEat> findEatBySickId(long sickId) {
        SickYangSheng sickYangSheng = this.getSickYangShengBySickId(sickId);
        String eatIds = sickYangSheng.getDietId();
        List<Long> ids = this.getIds(eatIds);
        List<YangShengEat> results = yangShengEatDao.findAllByIdIn(ids);
        return results;
    }

    @Override
    public List<YangShengTea> findTeaBySickId(long sickId) {
        SickYangSheng sickYangSheng = this.getSickYangShengBySickId(sickId);
        String teaIds = sickYangSheng.getTeaId();
        List<Long> ids = this.getIds(teaIds);
        List<YangShengTea> results = yangShengTeaDao.findAllByIdIn(ids);
        return results;
    }

    @Override
    public List<YangShengAcupuncture> findAcupunctureBySickId(long sickId) {
        SickYangSheng sickYangSheng = this.getSickYangShengBySickId(sickId);
        String moxibustionIds = sickYangSheng.getMoxibustionId();
        List<Long> ids = this.getIds(moxibustionIds);
        List<YangShengAcupuncture> results = yangShengAcupunctureDao.findAllByIdIn(ids);
        return results;
    }

    @Override
    public List<YangShengMethod> findMethodBySickId(long sickId) {
        SickYangSheng sickYangSheng = this.getSickYangShengBySickId(sickId);
        String methodIds = sickYangSheng.getMedicineId();
        List<Long> ids = this.getIds(methodIds);
        List<YangShengMethod> results = yangShengMethodDao.findAllByIdIn(ids);
        return results;
    }

    /**
     * 为病历绑定养生建议
     *
     * @param
     */
    private void addYangShengAdvice(long sickId) {
//        for (SickInfo sickInfo : sickInfos) {
        SickInfo sickInfo = sickInfoDao.findById(sickId).get();
        SickYangSheng sickYangsheng = sickYangShengDao.findOneBySickId(sickId);
        if (sickYangsheng == null) {
            doAddYangSheng(sickInfo);
        }
//        }
    }

    private void doAddYangSheng(SickInfo sickInfo) {
        YangShengConfig yangShengConfig = yangShengConfigDao.findAll().iterator().next();
        SickYangSheng sickYangSheng = new SickYangSheng();
        sickYangSheng.setSickId(sickInfo.getId());

        int xieziNum = yangShengConfig.getXieZiNum();
        List<YangShengXieZi> yangShengXieZis = yangShengXieZiDao.findAllByRand(xieziNum);
        String xieziIds = yangShengXieZis.stream().map(e -> String.valueOf(e.getId())).collect(Collectors.joining(","));
        sickYangSheng.setXieZiId(xieziIds);

        int sportTag0Num = yangShengConfig.getSportTag0Num();
        int sportTag1Num = yangShengConfig.getSportTag1Num();
        List<YangShengSports> sports0List = yangShengSportDao.findALLByRand(0, sportTag0Num);
        List<YangShengSports> sports1List = yangShengSportDao.findALLByRand(1, sportTag1Num);
        sports0List.addAll(sports1List);
        String sportIds = sports0List.stream().map(e -> String.valueOf(e.getId())).collect(Collectors.joining(","));
        sickYangSheng.setSportId(sportIds);

        String seasonConfig = yangShengConfig.getSeasonNum();
        Map<Integer, Integer> configs = Arrays.stream(seasonConfig.split(",")).collect(Collectors.toMap(a -> Integer.valueOf(a.split(":")[0]), a -> Integer.valueOf(a.split(":")[1])));
        int seasonTag = this.getSeasonTag();
        int seasonNum = configs.get(seasonTag);
        List<YangShengSeaon> yangShengSeaons = yangShengSeaonDao.findAllByRand(seasonTag, seasonNum);
        String seasonIds = yangShengSeaons.stream().map(e -> String.valueOf(e.getId())).collect(Collectors.joining(","));
        sickYangSheng.setSeasonId(seasonIds);

        String dietInfo = Optional.ofNullable(sickInfo.getDietInfo()).orElse("");
        List<String> dietNames = Arrays.asList(dietInfo.split(","));
        List<YangShengEat> yangShengEats = yangShengEatDao.findAllByDietNameIn(dietNames);
        String eatIds = yangShengEats.stream().map(e -> String.valueOf(e.getId())).collect(Collectors.joining(","));
        sickYangSheng.setDietId(eatIds); // 膳食

        String medicineInfo = Optional.ofNullable(sickInfo.getMedicineInfo()).orElse("");
        List<String> medicineNames = Arrays.asList(medicineInfo.split(","));
        List<YangShengMethod> yangShengMethods = yangShengMethodDao.findAllByMedicineNameIn(medicineNames);
        String methodIds = yangShengMethods.stream().map(e -> String.valueOf(e.getId())).collect(Collectors.joining(","));
        sickYangSheng.setMedicineId(methodIds); //药浴

        String teaInfo = Optional.ofNullable(sickInfo.getTeaInfo()).orElse("");
        List<String> teaNames = Arrays.asList(teaInfo.split(","));
        List<YangShengTea> yangShengTeas = yangShengTeaDao.findAllByTeaNameIn(teaNames);
        String teaIds = yangShengTeas.stream().map(e -> String.valueOf(e.getId())).collect(Collectors.joining(","));
        sickYangSheng.setTeaId(teaIds); //

        String moxibustionHealth = Optional.ofNullable(sickInfo.getMoxibustionHealth()).orElse("");
        List<String> moxibustionHealths = Arrays.asList(moxibustionHealth.split(","));
        List<YangShengAcupuncture> yangShengAcupunctures = yangShengAcupunctureDao.findAllByMoxibustionNameIn(moxibustionHealths);
        String moxibustionHealthIds = yangShengAcupunctures.stream().map(e -> String.valueOf(e.getId())).collect(Collectors.joining(","));
        sickYangSheng.setMoxibustionId(moxibustionHealthIds); //艾灸

        sickYangShengDao.save(sickYangSheng);
    }

    private int getSeasonTag() {
        // 3～5月为春季，6～8月为夏季，9～11月为秋季，12月～来年2月为冬季
        int month = Calendar.getInstance().get(Calendar.MONTH);// 从0开始
        month++;
        if (month >= 3 && month <= 5) {
            return 1;// 春季
        }
        if (month >= 6 && month <= 8) {
            return 2;// 春季
        }
        if (month >= 9 && month <= 11) {
            return 3;// 春季
        }
        if (month == 12 || month <= 2) {
            return 4;// 春季
        }
        return month;
    }

    private SickYangSheng getSickYangShengBySickId(long sickId) {
        SickYangSheng sickYangSheng = sickYangShengDao.findOneBySickId(sickId);
        if (sickYangSheng == null) {
            throw new BusinessException("尚未给出养生建议");
        }
        return sickYangSheng;
    }

    private List<Long> getIds(String ids) {
        return Arrays.stream(ids.split(",")).map(id -> Long.valueOf(id)).collect(Collectors.toList());
    }

    private String generateToken(String phone) {
        String token = DigestUtils.md5DigestAsHex(phone.getBytes());
        redisCache.setValue(Constants.SESSION_PREFIX + token, phone);
        return token;
    }

}
